<?php


namespace WenRuns\Laravel;

use Illuminate\Support\Facades\Cache as LaravelCache;
use WenRuns\Laravel\Cache\Redis;

class Cache extends LaravelCache
{
    protected static $DRIVER = null;

    const ROW = '@row@';

    /**
     * @return \Illuminate\Config\Repository|\Illuminate\Contracts\Foundation\Application|mixed|null
     */
    public static function getDriver()
    {
        if (empty(self::$DRIVER)) {
            self::$DRIVER = config('cache.default', 'file');
        }
        return self::$DRIVER;
    }

    /**
     * @param $key
     * @param $values
     * @param null $ttl
     * @return bool
     */
    public static function append($key, $values, $ttl = null)
    {
        switch (self::getDriver()) {
            case 'redis':
                $res = Redis::rpush($key, $values);
                break;
            default:
                if (self::has($key)) {
                    $values = Cache::get($key) . self::ROW . (is_array($values) ? implode(self::ROW, $values) : $values);
                }
                $res = Cache::put($key, $values, $ttl);
        }
        return $res;
    }

    /**
     * @param $key
     * @param null $default
     * @param false $keep
     * @return false|mixed|string[]|null
     */
    public static function take($key, $default = null, $keep = false)
    {
        $res = $default;
        switch (self::getDriver()) {
            case 'redis':
                if (Redis::exists($key)) {
                    $res = Redis::lrange($key, 0, Redis::llen($key));
                    if (!$keep) {
                        Redis::ltrim($key, 0, -1);
                    }
                }
                break;
            default:
                if (self::has($key)) {
                    $res = explode(self::ROW, self::get($key));
                    if (!$keep) {
                        self::forget($keep);
                    }
                }
        }
        return is_array($res) ? array_filter($res) : $res;
    }

    /**
     * @param $key
     */
    public static function clear($key)
    {
        switch (self::getDriver()) {
            case 'redis':
                Redis::ltrim($key, 0, -1);
                break;
            default:
                self::pull($key);
        }
    }

    /**
     * @param $key
     * @param \Closure $closure
     */
    public static function loop($key, \Closure $closure)
    {
        switch (self::getDriver()) {
            case 'redis':
                $k = 0;
                while ($item = Redis::lpop($key)) {
                    call_user_func($closure, $item, $k++);
                }
                break;
            default:
                foreach (self::take($key, []) as $k => $item) {
                    call_user_func($closure, $item, $k);
                }
        }
    }
}
